import type { Directive, DirectiveBinding } from "vue";

/**
 * v-debounce
 * 按钮防抖指令，可自行扩展至input
 * 接收参数：function类型
 */
interface ElType extends HTMLElement {
  __handleClick__: () => any;
}

export const debounce: Directive = {
  /**
   * 当指令绑定的元素被挂载时，处理点击事件以触发回调函数
   * 此函数用于实现一个防抖效果，即连续点击只会触发一次回调函数
   *
   * @param el 绑定指令的元素
   * @param binding 指令的绑定对象，包含值(value)等信息
   * @throws {Error} 如果回调值不是函数类型，则抛出错误
   */
  mounted(el: ElType, binding: DirectiveBinding) {
    // 检查绑定值是否为函数类型，否则抛出错误
    if (typeof binding.value !== "function") {
      throw "callback must be a function";
    }
    // 定义一个定时器变量，初始值为null
    let timer: number | null = null;
    const handleClick = () => {
      if (timer) {
        clearInterval(timer);
      }
      timer = setTimeout(() => {
        binding.value();
      }, 500);
    };
    el.__handleClick__ = handleClick;
    el.addEventListener("click", el.__handleClick__);
    el.addEventListener("keydown", (event: KeyboardEvent) => {
      if (event.key === "Enter") {
        // 回车键
        handleClick();
      }
    });
  },
  /**
   * 在组件卸载前，移除点击事件监听器
   *
   * 此方法的目的是为了在组件卸载时，避免内存泄漏或不必要的事件监听器留在DOM中
   * 通过移除事件监听器，可以帮助确保应用的性能和内存管理处于最优状态
   *
   * @param el - ElType类型的元素，表示需要处理的DOM节点
   *             我们在此处移除此节点上绑定的特定点击事件监听器
   */
  beforeUnmount(el: ElType) {
    el.removeEventListener("click", el.__handleClick__);
    el.removeEventListener("keydown", el.__handleClick__);
  },
};
